package com.chen.common.dataSource.aop;

import com.chen.base.utils.JoinPointUtil;
import com.chen.common.dataSource.annotation.DS;
import com.chen.common.dataSource.config.DataSourceThreadLocal;
import com.chen.common.dataSource.constant.DataSourceConstant;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

 
/**
 * 多数据源，切面处理类
 * @author ~龙~
 */
@Slf4j
@Order(1)
@Aspect
@Component
public class DataSourceAop {

    /**
     * @annotation 匹配指定注解的方法
     * @within 匹配指定注解的类
     * 注意：这里只拦截所注解的类，如果调用的是父类的方法，那么不会拦截，除非父类方法在子类中被覆盖。
     */
    @Pointcut("@annotation(com.chen.common.dataSource.annotation.DS) || " +
              "@within(com.chen.common.dataSource.annotation.DS)")
    public void dataSourceCut() {}

    @After("dataSourceCut()")
    public void after(JoinPoint point){
        DataSourceThreadLocal.del();
    }
 
    @Around("dataSourceCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        DS dsMethod = JoinPointUtil.getMethodAnnotation(point, DS.class);
        DS dsClass = JoinPointUtil.getClassAnnotation(point, DS.class);
        if(dsMethod != null) {
            //方法优先，如果方法上存在注解，则优先使用方法上的注解
            DataSourceThreadLocal.setDataSourceKey(dsMethod.value());
        }else if(dsClass != null) {
            //其次类优先，如果类上存在注解，则使用类上的注解
            DataSourceThreadLocal.setDataSourceKey(dsClass.value());
        }else {
            //如果都不存在，则使用默认
            DataSourceThreadLocal.setDataSourceKey(DataSourceConstant.PRIMARY_DS);
        }

        return point.proceed();
    }
}